﻿/**
 * @brief     自定义日志记录
 * @details   可记录不同级别的信息，包括出错的文件、行号、错误信息等。（自定义）
 * @author
 * @version   1.0
 * @date      2017-12-13
 * @copyright
 * @note 2018-03-08:Will:修复多线程访问，因未加互斥锁产生的奔溃问题;
 *        2018-12-07:Will:精简文件名、函数名显示
 *	
	Common::SystemLogFile::SystemLogConfigInfo LogConfig;
	LogConfig.isRecordFile = true;
	LogConfig.level = Common::SystemLogFile::SYSTEMLOG_INFO;
	Common::SystemLogFile *m_pSystemLogFile = new Common::SystemLogFile();
	m_pSystemLogFile->init(LogConfig);
 *
	SYSTEMLOG_DEBUG(QString("---000000---------main thread Test--!").toStdString().data());
	SYSTEMLOG_INFO(QString("---000000---------main thread Test--!").toStdString().data());
	SYSTEMLOG_WARNING(QString("---000000---------main thread Test--!").toStdString().data());
	SYSTEMLOG_ERROR(QString("---000000---------main thread Test--!").toStdString().data());
 */
#ifndef SYSTEMLOGFILE_H
#define SYSTEMLOGFILE_H

#include <QObject>
#include <QFile>

#include "common_global.h"

namespace Common {

	class COMMONSHARED_EXPORT  SystemLogFile : public QObject
	{
		Q_OBJECT
	public:
		/*!
		 *  @brief 日志等级
		 */
		enum SYSTEMLOG_LEVEL {
			SYSTEMLOG_DEBUG,                        /*!< 调试 */
			SYSTEMLOG_INFO,                         /*!< 提示 */
			SYSTEMLOG_WARNING,                      /*!< 警告 */
			SYSTEMLOG_ERROR,                        /*!< 错误 */
			SYSTEMLOG_FATAL                         /*!< 致命的错误 */
		};
		Q_FLAG(SYSTEMLOG_LEVEL)

			/**
			 * @brief 系统日志配置信息
			 */
			struct SystemLogConfigInfo {
			SystemLogConfigInfo() : isRecordFile(false), level(0) {

			}

			bool isRecordFile;                     /*!< 是否记录到文件 */
			int level;                             /*!< 记录日志等级，大于等于此level的日志将被记录 */
		};

	public:
		explicit SystemLogFile();
		~SystemLogFile();

	public:
		/**
		 * @brief	setLogLevel 设置日志等级
		 * @param	level
		 */
		void setLogLevel(const SYSTEMLOG_LEVEL & level);

		/**
		 * @brief	getLogLevel 获取日志等级
		 * @return
		 */
		SYSTEMLOG_LEVEL getLogLevel() { return m_logLevel; }

		/**
		 * @brief init 初始化
		 * @param logConfig 日志配置信息
		 * @return
		 */
		static bool init(SystemLogConfigInfo & logConfig);

		/**
		 * @brief log
		 * @param nLevel
		 * @param fileDesc
		 * @param functionDesc
		 * @param lineNum
		 * @param data
		 */
		static void log(SYSTEMLOG_LEVEL nLevel, const char * fileDesc, const char * functionDesc, int lineNum, const char* data, ...);

	private:
		static QString getLeveDesc(SYSTEMLOG_LEVEL level);

	private:
		static bool m_isRecord2File;
		static bool m_isFileReady;
		static SYSTEMLOG_LEVEL m_logLevel;
	};

}//namespace Common

#ifdef Q_OS_WIN
#define FILE_SEPARATOR '\\'
#else
#define FILE_SEPARATOR '/'
#endif

#define FUNC_SEPARATOR '::'

#ifndef QT_NO_DEBUG
#define __FILENAME__ (strrchr(__FILE__, FILE_SEPARATOR) ? (strrchr(__FILE__, FILE_SEPARATOR) + 1):__FILE__)
#define __FUNNAME__ (strrchr(__FUNCTION__,FUNC_SEPARATOR)?(strrchr(__FUNCTION__, FUNC_SEPARATOR) + 1):__FUNCTION__)
#else
#define __FILENAME__ NULL
#define __FUNNAME__ NULL
#endif

#define SYSTEMLOG_DEBUG(...)      Common::SystemLogFile::log(Common::SystemLogFile::SYSTEMLOG_DEBUG, __FILENAME__, __FUNNAME__, __LINE__, __VA_ARGS__)
#define SYSTEMLOG_INFO(...)       Common::SystemLogFile::log(Common::SystemLogFile::SYSTEMLOG_INFO, __FILENAME__, __FUNNAME__, __LINE__, __VA_ARGS__)
#define SYSTEMLOG_WARNING(...)    Common::SystemLogFile::log(Common::SystemLogFile::SYSTEMLOG_WARNING, __FILENAME__, __FUNNAME__, __LINE__, __VA_ARGS__)
#define SYSTEMLOG_ERROR(...)      Common::SystemLogFile::log(Common::SystemLogFile::SYSTEMLOG_ERROR, __FILENAME__, __FUNNAME__, __LINE__, __VA_ARGS__)
#define SYSTEMLOG_FATAL(...)      Common::SystemLogFile::log(Common::SystemLogFile::SYSTEMLOG_FATAL, __FILENAME__, __FUNNAME__, __LINE__, __VA_ARGS__)

#endif // SYSTEMLOGFILE_H
